/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.openide.src; import java.beans.*; import java.io.*; import java.util.StringTokenizer; import javax.swing.text.DefaultStyledDocument; import org.openide.nodes.Node; import org.openide.text.IndentEngine; import org.openide.filesystems.FileUtil; /** Base class for representations of elements in the * Java language. * All elements are items which are structural features of a class (or the class itself), * rather than corresponding to bytecode (i.e. statements are not represented). * The same representation is suited to any language using the Java VM. * * @author Jaroslav Tulach, Petr Hamernik */ public abstract class Element extends Object implements Serializable, ElementProperties, Node.Cookie { /** Implementation */ Impl impl; static final long serialVersionUID =967040188302141522L; /** Create a new element with the provided implementation. The implementation is * responsible for storing all properties of the object. * * @param impl the implementation to use */ protected Element(Impl impl) { this.impl = impl; impl.attachedToElement (this); } /** Add a property change listener. * @param l the listener to add * @see ElementProperties */ public final void addPropertyChangeListener (PropertyChangeListener l) { impl.addPropertyChangeListener (l); } /** Remove a property change listener. * @param l the listener to remove * @see ElementProperties */ public final void removePropertyChangeListener (PropertyChangeListener l) { impl.removePropertyChangeListener (l); } /** Mark the current element in the context of this element. * The current element means the position for inserting new elements. * @param beforeAfter <CODE>true</CODE> means that new element is inserted before * the specified element, <CODE>false</CODE> means after. */ public void markCurrent(boolean beforeAfter) { impl.markCurrent(beforeAfter); } /** Look for a cookie providing added behavior for this element. * The request is {@link Impl#getCookie delegated} to the current implementation. * Also note that <code>Element</code> implements <code>Node.Cookie</code>, and that * if the implementation does not provide a cookie, but the requested cookie class is * actually a superclass/interface of this element type, then the element itself may be * returned as the cookie. * @param type the cookie class to look for * @return a cookie assignable to that class, or <code>null</code> if the cookie * is not supported */ public Node.Cookie getCookie(Class type) { Node.Cookie c = impl.getCookie(type); if ((c == null) && type.isAssignableFrom(getClass())) c = this; return c; } private Object writeReplace() { return impl; } /** Print this element (and all its subelements) into an element printer. * @param printer the element printer * @exception ElementPrinterInterruptException if the printer canceled the printing */ public abstract void print(ElementPrinter printer) throws ElementPrinterInterruptException; /** Prints array of elements. * @param el the elements * @param printer The printer where to write * @return true if at least one element was printed * @exception ElementPrinterInterruptException if printer cancel the printing */ static boolean print(Element[] el, ElementPrinter printer) throws ElementPrinterInterruptException { for (int i = 0; i < el.length; i++) { if (i > 0) { printer.println(""); // NOI18N printer.println(""); // NOI18N } el[i].print(printer); } return (el.length > 0); } /** Prints the javadoc to the printer. * It calls doc.getRawText() and inserts the '*' symbols to the begins * of lines. * @param doc The printed javadoc * @param printer The printer where to write * @exception ElementPrinterInterruptException if printer cancel the printing */ static void printJavaDoc(JavaDoc doc, ElementPrinter printer) throws ElementPrinterInterruptException { if (doc.isEmpty()) return; //PENDING: should be more customizable StringTokenizer tukac = new StringTokenizer(doc.getRawText(), "\n", true); // NOI18N printer.print("/**"); boolean oneMoreSpace = true; boolean newLine = false; while (tukac.hasMoreTokens()) { String token = tukac.nextToken(); newLine = token.equals("\n"); if (newLine) { printer.println(""); printer.print(" *"); oneMoreSpace = true; } else { if (oneMoreSpace && !token.startsWith(" ")) { printer.print(" "); oneMoreSpace = false; } printer.print(token); } } if (!newLine) printer.print(" *"); printer.print("/"); } /** Get a string representation of the element. * @return the string * @see #print * @see DefaultElementPrinter */ public String toString() { StringWriter sw = new StringWriter(); IndentEngine indentator = IndentEngine.find(FileUtil.getMIMEType("java")); // NOI18N PrintWriter pw = new PrintWriter(indentator.createWriter(new DefaultStyledDocument(), 0, sw)); // PrintWriter pw = new PrintWriter(sw); try { print(new DefaultElementPrinter(pw)); } catch (ElementPrinterInterruptException e) { // could not happen. } pw.close(); return sw.toString(); } /** Pluggable implementation of the storage of element properties. * @see Element#Element */ public interface Impl extends Serializable { static final long serialVersionUID =-3246061193296761293L; /** Called to attach the implementation to a specific * element. Will be called in the element's constructor. * Allows implementors * of this interface to store a reference to the holder class, * useful for implementing the property change listeners. * * @param element the element to attach to */ public void attachedToElement (Element el); /** Add a property change listener. * @param l the listener to add */ public void addPropertyChangeListener (PropertyChangeListener l); /** Remove a property change listener. * @param l the listener to remove */ public void removePropertyChangeListener (PropertyChangeListener l); /** Implementations must be resolvable. * I.e., upon deserialization they must be able to recreate the * holder class. * @return an instance of the proper subclass of {@link Element} * @see Serializable */ public Object readResolve(); /** Get the support for a cookie, if any. * Changes of supported cookies are <em>not</em> fired. * * @param type the cookie class to look for * @return an instance assignable to that class, or <code>null</code> if the cookie * is not supported */ public Node.Cookie getCookie(Class type); /** Mark the current element in the context of this element. * The current element means the position for inserting new elements. * @param beforeAfter <CODE>true</CODE> means that new element is inserted before * the specified element, <CODE>false</CODE> means after. */ public void markCurrent(boolean beforeAfter); } /** Default implementation of the Impl interface. * It just holds the property values. */ static abstract class Memory implements Element.Impl { /** the element for this implementation */ protected Element element; /** Property change support */ private PropertyChangeSupport support; static final long serialVersionUID =7734412320645883859L; /** Attaches to element */ public void attachedToElement (Element element) { this.element = element; } /** Fires property change event. * @param name property name * @param o old value * @param n new value */ protected final void firePropertyChange (String name, Object o, Object n) { if (support != null) { support.firePropertyChange (name, o, n); } } /** Adds property listener */ public synchronized void addPropertyChangeListener (PropertyChangeListener l) { if (support == null) { synchronized (this) { // new test under synchronized block if (support == null) { support = new PropertyChangeSupport (element); } } } support.addPropertyChangeListener (l); } /** Removes property listener */ public void removePropertyChangeListener (PropertyChangeListener l) { if (support != null) { support.removePropertyChangeListener (l); } } /** This implementation returns always null. * @param type the class to look for * @return null. */ public Node.Cookie getCookie(Class type) { return null; } /** Mark the current element in the context of this element. * The current element means the position for inserting new elements. * @param beforeAfter <CODE>true</CODE> means that new element is inserted before * the specified element, <CODE>false</CODE> means after. */ public void markCurrent(boolean beforeAfter) { //PENDING } } } /* * Log * 24 src-jtulach1.23 1/12/00 Petr Hamernik i18n using perl script * (//NOI18N comments added) * 23 src-jtulach1.22 1/11/00 Petr Hamernik fixed 5287 * 22 src-jtulach1.21 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 21 src-jtulach1.20 9/27/99 Petr Hamernik indenting improved * (empty lines between methods) * 20 src-jtulach1.19 8/9/99 Ian Formanek Generated Serial Version * UID * 19 src-jtulach1.18 7/19/99 Petr Hamernik IndentEngine usage added * 18 src-jtulach1.17 7/8/99 Petr Hamernik inserting position added * 17 src-jtulach1.16 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 16 src-jtulach1.15 6/7/99 Petr Hamernik indent engine used - * must be uncommented (depends on text editor change) * 15 src-jtulach1.14 5/10/99 Petr Hamernik javadoc & printing * improved * 14 src-jtulach1.13 4/30/99 Jesse Glick [JavaDoc] * 13 src-jtulach1.12 4/26/99 Jesse Glick [JavaDoc] * 12 src-jtulach1.11 4/26/99 Petr Hamernik getCookie minor changes * 11 src-jtulach1.10 4/13/99 Petr Hamernik Element implements * Node.Cookie * 10 src-jtulach1.9 3/30/99 Jesse Glick [JavaDoc] * 9 src-jtulach1.8 3/22/99 Petr Hamernik printing changed * 8 src-jtulach1.7 3/18/99 Petr Hamernik * 7 src-jtulach1.6 2/17/99 Petr Hamernik serialization changed. * 6 src-jtulach1.5 2/16/99 Petr Hamernik * 5 src-jtulach1.4 2/8/99 Petr Hamernik * 4 src-jtulach1.3 1/19/99 Jaroslav Tulach * 3 src-jtulach1.2 1/19/99 Jaroslav Tulach * 2 src-jtulach1.1 1/19/99 Jaroslav Tulach * 1 src-jtulach1.0 1/17/99 Jaroslav Tulach * $ */